import { AsyncStorage } from 'react-native'
import Trending from 'GitHubTrending' //获取github trend数据, github没有提供专门的接口

export const FLAG_STORAGE = {
	flag_popular: 'popular',
	flag_trending: 'trending'
}

/**
 * 离线缓存的几种策略
 * 1.优先从本地获取数据，如果数据过时或不存在就从服务器获取数据，数据返回后同时将数据同步到本地数据库
 * 2.优先从服务器获取数据，数据返回后同时将数据同步到本地数据库，如果网络故障则从本地获取数据
 * 3.同时从本地和服务器获取数据，如果本地数据库返回数据则先展示本地数据，等网络数据回来后再展示网络数据同时将数据同步到本地数据库
 *
 * 以下以第一种策略实现离线缓存
 */

export default class DataStore {
	/**
	 * 获取数据，优先获取本地数据，如果无本地数据或本地数据过期则获取网络数据
	 * @param url
	 * @param flag
	 * @return {Promise<R>}
	 */
	fetchData(url, flag) {
		return new Promise((resolve, reject) => {
			this.fetchLocalData(url)
				.then(wrapData => {
					if (
						wrapData &&
						DataStore.checkTimestampValid(wrapData.timestamp)
					) {
						resolve(wrapData)
					} else {
						this.fetchNetData(url, flag)
							.then(data => {
								resolve(this._wrapData(data))
							})
							.catch(error => {
								reject(error)
							})
					}
				})
				.catch(error => {
					this.fetchNetData(url, flag)
						.then(data => {
							resolve(this._wrapData())
						})
						.catch(error => {
							reject(error)
						})
				})
		})
	}

	/**
	 * 检查timestamp是否在有效期内
	 * @param timestamp 项目更新时间
	 * @return {boolean}  true不需要更新, false需要更新
	 */
	static checkTimestampValid(timestamp) {
		const currentDate = new Date()
		const targetDate = new Date()
		targetDate.setTime(timestamp)
		if (currentDate.getMonth() !== targetDate.getMonth()) {
			return false
		}
		if (currentDate.getDate() !== targetDate.getDate()) {
			return false
		}
		//有效期4个小时
		if (currentDate.getHours() - targetDate.getHours() > 4) {
			return false
		}
		return true
	}

	/**
	 * 获取本地数据
	 * @param url
	 * @return {Promise<R>}
	 */
	fetchLocalData(url) {
		return new Promise((resolve, reject) => {
			AsyncStorage.getItem(url, (error, result) => {
				if (!error) {
					try {
						resolve(JSON.parse(result))
					} catch (e) {
						reject(e)
						console.log(e)
					}
				} else {
					reject(error)
					console.log(error)
				}
			})
		})
	}

	/**
	 * 获取网络数据
	 * @param url
	 * @param flag
	 * @return {Promise<R>}
	 */
	fetchNetData(url, flag) {
		return new Promise((resolve, reject) => {
			if (flag !== FLAG_STORAGE.flag_trending) {
				fetch(url)
					.then(response => {
						if (response.ok) {
							return response.json()
						}
						throw new Error('Network response was not ok')
					})
					.then(responseData => {
						this.saveData(url, responseData)
						resolve(responseData)
					})
					.catch(error => {
						reject(error)
					})
			} else {
				//获取趋势模块的数据 github没有提供api接口
				new Trending()
					.fetchTrending(url)
					.then(items => {
						if (!items) {
							throw new Error('responseData is null')
						}
						this.saveData(url, items)
						resolve(items)
					})
					.catch(error => {
						reject(error)
					})
			}
		})
	}

	/**
	 * 保存数据
	 * @param url
	 * @param data
	 * @param callback
	 */
	saveData(url, data, callback) {
		if (!data || !url) {
			return
		}
		AsyncStorage.setItem(url, JSON.stringify(this._wrapData(data)), callback)
	}

	_wrapData(data) {
		return { data: data, timestamp: new Date().getTime() }
	}
}
